Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6409 +/- ##
==========================================
- Coverage 78.97% 78.97% -0.01%
==========================================
Files 684 684
Lines 294201 294986 +785
Branches 8670 8670
==========================================
+ Hits 232359 232964 +605
- Misses 60030 60214 +184
+ Partials 1812 1808 -4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
stertooy
left a comment
There was a problem hiding this comment.
Very happy to see this PR revived!
One thing I'm a bit wary of, is how PreImagesSet( f, U ) always returns [ ] if U is not a subset of Range( f ), even if they have non-empty intersection. Intuitively, I would expect this function to follow the standard(?) mathematical definition of
PreImagesSetNC( Intersection( Range( f ), U ) )
|
@stertooy It's so good to get feedback on this work - I will get on with making the changes you suggest. |
|
Now I am really confused. The manual states: "If elms is a subset of the range of the general mapping map then PreImagesSet returns the set of all preimages of elms under map." Sticking to that, PreImagesSet should return fail if U is not a subset of the range. Alternatively, we could ditch PreImagesSetNC, and redefine PreImagesSet to return the preimage of the intersection, which could be []. |
|
Perhaps this is why I returned [] in PreImagesElm when the test failed: |
I think the question is what we want the non-NC functions to do for elements/sets not contained in the range. I see two options:
The former option keeps the NC and non-NC versions closer together, with the only difference being a extra check, which is what an NC version usually indicates in GAP. The latter option sticks closer to the standard mathematical definitions. Either option is fine with me (with a preference for option 2), but it should at least be consistent across all the affected functions.
I think we should still keep Perhaps @fingolfin @ThomasBreuer @hulpke want to weigh in, given that they were active in #4809 and #5173? |
|
Thanks for working on this again, @cdwensley. Unfortunately I don't have the bandwidth available to read all here, think about it, and come up with a good stance right now -- we'll get there, but I am afraid not in time for GAP 4.16.0 -- but I am confident it'll get merged eventually, certainly before 4.17.0. I'll try to get back to this when I have some mental capacity for it |
|
I think part of the reason of NC functions is to actually not have to worry about issues such as membership (which might require an extra test). |
|
Never expected it to make 4.16.0 but I will try to keep it up-to-date with gapdev.On 28 May 2026, at 01:03, Max Horn ***@***.***> wrote:fingolfin left a comment (gap-system/gap#6409)
Thanks for working on this again, @cdwensley. Unfortunately I don't have the bandwidth available to read all here, think about it, and come up with a good stance right now -- we'll get there, but I am afraid not in time for GAP 4.16.0 -- but I am confident it'll get merged eventually, certainly before 4.17.0.
I'll try to get back to this when I have some mental capacity for it
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Agree - will make adjustments in due course.On 28 May 2026, at 02:49, Alexander Hulpke ***@***.***> wrote:hulpke left a comment (gap-system/gap#6409)
I think part of the reason of NC functions is to actually not have to worry about issues such as membership (which might require an extra test).
I.e. the result of PreImagesSetNC should undefined if the set is not in the image of the map, but if it is returns the same as PreImagesSet.
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
There was a problem hiding this comment.
This file was added by accident and should be removed again.
ThomasBreuer
left a comment
There was a problem hiding this comment.
Up to now, PreImagesSomething( map, obj ) is defined as follows.
If obj is not an element (or subset, respectively) of Range( map ) then anything may happen.
If obj is an element (or subset, respectively) of Range( map ) but not of Image( map ) then fail is returned.
Otherwise, an element (or subset, respectively) of Source( map ) is returned that maps to obj under map.
The idea of the current pull request is to define functions PreImagesSomethingNC with the above definition, and to change the functions PreImagesSomething to signal an error if obj is not an element (or subset, respectively) of Range( map ), and to do the same as PreImagesSomethingNC otherwise.
Thus an error message is guaranteed for PreImagesSomething in the former case, and the user can decide to omit the membership test in Range( map ) by calling PreImagesSomethingNC.
(The text for the release notes would look like that if the pull request gets merged in this form.)
The proposed changes do not address the problems in the example from #4809 and in the second example from #4088, where one asks for the preimage of an element that is in the range but not in the image of the map.
My understanding of the discussion in #4088 was that the membership test for obj in the image of map is what one wants to skip in the new NC variants.
(If this is the case then it will be not difficult to change the pull request accordingly.)
The documentation of the functions should say that fail is returned if obj is not an element (or subset) of the range of map. Currently the proposed text says that the membership is tested.
(An alternative to a fail result would be an error. Of course, if we change the code such that membership in the image of map is tested, then a fail result is correct.)
| if not ( n in Range(rel) ) then | ||
| return fail; | ||
| fi; | ||
| return PreImagesElm( rel, n ); |
There was a problem hiding this comment.
| return PreImagesElm( rel, n ); | |
| return PreImagesElmNC( rel, n ); |
| ## From &GAP; version 4.16.0 <C>PreImagesRepresentative</C> | ||
| ## was renamed <C>PreImagesRepresentativeNC</C> throughout the library, | ||
| ## and <C>PreImagesRepresentative</C> now checks that <A>elm</A> is an | ||
| ## element of the range before calling <C>PreImagesRepresentativeNC</C>. |
There was a problem hiding this comment.
The definition should say what happens if this check fails.
| ## From &GAP; version 4.16.0 <C>PreImagesSet</C> | ||
| ## has been renamed <C>PreImagesSetNC</C> throughout the library, | ||
| ## and <C>PreImagesSet</C> now checks that <A>elms</A> is a | ||
| ## subset of the range before calling <C>PreImagesSetNC</C>. |
There was a problem hiding this comment.
The definition should say what happens if this check fails.
There was a problem hiding this comment.
Many thanks for all these suggestions and making it clear how to proceed.
I have dealt with most of these suggestions, but there is more work to do.
Are we now agreed that, for the non-NC versions:
- elm/elms/coll not in the range => an Error is thrown, and
- elm/elms/coll in the range but not the image => fail is returned?
That being the case, I am adding error messages.
There was a problem hiding this comment.
Yes, this is how I understand the discussions in #4088 and #4809.
The "Error is thrown" part is changed behaviour in the sense that the current documentation promises nothing in this situation, hence the documentation should state that now an error is promised.
The "fail is returned" part is a bugfix in the sense that the documentation promises this but the current code does not follow this rule. (The examples in #4088 show that the current code may return a wrong element or run into an error.)
And the new NC variants allow one to skip the checks that are necessary to achieve these changes.
|
Advice required about PreImagesSet. If R is the range of map, and if the set U is a subset of R such that the intersection of U and the image of map is V then, mathematically, PreImagesSet(U) is PreImagesSet(V). Is that what should be implemented? At present, fail is returned. |
I see, The documentation of |
Is it not acceptable to have or perhaps, if Something like this means we keep the old definition of |
Proceeding like this means:
I think this is acceptable. We make sue that elements not in the image do not cause trouble, and the (Delegating from |
|
The proposal from @ThomasBreuer seems very sensible, and I shall proceed to make the suggested changes. |
ThomasBreuer
left a comment
There was a problem hiding this comment.
Some containment checks for the range should become containment checks for the image.
(I hope that the new tests will not cause infinite loops of the kind that PreImage( map ) calls PreImagesSet( map, Image( map ) ), and Image( map ) calls ImagesSet( map, PreImage( map ) ). However, if that should happens then the question is why this did not cause problems i nthe past.)
|
Many thanks @ThomasBreuer for all these corrections - sorry about the silly error. |
ThomasBreuer
left a comment
There was a problem hiding this comment.
Thanks.
One more suggestion for fixing a typo.
And I am wondering whether also PreImageElm should be changed in the same spirit.
What is missing now is some text for the release notes. The following description would fit but is admittedly quite long.
- Change the definitions of
PreImagesElm,PreImagesRepresentative,PreImagesSetin the case that the given element or set is not contained in theRangeof the general mapping:
Up to now, nothing was guaranteed in this case.
From now on, an error message is shown in this case. - Introduce new operations
PreImagesElmNC,PreImagesRepresentativeNC,PreImagesSetNC,
turn all GAP library methods forPreImagesElm,PreImagesRepresentative,PreImagesSetinto methods for the newNCvariants, and install methods for the non-NCvariants that first test the given element or set for containment in theRangeof the given general mapping and then delegate to theNCvariants. - In all GAP library methods for
PreImagesElm,PreImagesRepresentative,PreImagesSet, check whether the given element or set is contained in theImageof the given general mapping.
Up to now, some of the methods had assumed this and thus gave a wrong answer if the assumption was wrong. - Users' code may benefit from changing calls to
PreImagesElm,PreImagesRepresentative,PreImagesSetinto calls of theNCvariants where possible.
|
Regarding PreImageElm - this only applies to bijective maps, and I see no reason to change it. |
|
Interestingly, PreImage is called around 150 times in the main library, but PreImages not at all. |
|
How many of these should be changed? For example, in ghomperm.gi, line 308, |
The documentation of
The idea was that |
|
Thanks for your comments. Away for a few days - will address them when we return. |
|
There was a merge conflict in |
|
As suggested last week I have removed the recently introduced PreImagesNC from the library, though PreImages remains. In fact there were 12 calls to PreImages in the library which were changed to PreImagesNC and are now back to PreImages (in alglie.gi, grp.gi, grpnice.gi, grpprmcs.gi, mapprep.gi and relation.gi). Entries for PreImages in mapping.gd and mapping.gi have reverted to the versions in master. |
ThomasBreuer
left a comment
There was a problem hiding this comment.
Thanks a lot for the changes, and sorry for not checking them earlier.
I have added a few comments which should be easy to address.
The only missing bit is then the remark for the release notes.
I think that this pull request can be described as follows.
- Fix the behaviour of the functions in question (in the sense of the examples from #4809).
- Introduce
NCvariants for the functions such that the newly introduced checks can be omitted in situations where they are unnecessary. - Change the GAP library such that these new
NCvariants are called. (For GAP package maintainers, we should give a hint that the code of their package may be slowed down by the new checks, and that the recommended solution is to use theNCvariants where appropriate.)
Once this is done, we should really merge this pull request.
(And afterwards we should think about follow-up changes for ImagesRepresentativeNC and related functions, since now we know which changes are needed.)
| # check that <elm> has at least one preimage under <map> | ||
| if IsEmpty( pres ) then | ||
| return fail; | ||
| return []; |
There was a problem hiding this comment.
I think the fail result is correct.
When PreImagesRepresentativeNC was called via a PreImagesRepresentative call then pres cannot be empty, but if one has called PreImagesRepresentativeNC directly then the statement "anything may happen if elm is not an element of the range of map" from the documentation does not cover all cases where elm is not an element of the image of map.
In this sense, we can either change the documentation of PreImagesRepresentativeNC to "anything may happen if elm is not an element of the image of map", or the PreImagesRepresentativeNC methods have to deal with the situation that elm is not in the image.
I prefer the former solution.
| ## If <A>elm</A> is not even in the range then an error is signalled. | ||
| ## <P/> | ||
| ## When using <C>PreImagesRepresentativeNC</C> anything may happen if | ||
| ## <A>elm</A> is not an element of the range of <A>map</A>. |
There was a problem hiding this comment.
| ## <A>elm</A> is not an element of the range of <A>map</A>. | |
| ## <A>elm</A> is not an element of the image of <A>map</A>. |
PreImagesRepresentative checks whether elm is in the image, from this point of view PreImagesRepresentativeNC can assume that elm is in the image, and need not deal with situations where this is not the case.
(See the comment about line 1316 of mapping.gi.)
|
Thanks @cdwensley -- I really hope we can finally get this in for GAP 4.17.0 |
|
@cdwensley I took the liberty of fixing the merge conflicts with |
|
@ThomasBreuer, @fingolfin : thanks for all these comments. Not sure when I shall be able to address them. |
|
I pushed two more commits (with AI assistance, see the 9f504d8 addresses the remaining review comments from @ThomasBreuer:
While reviewing I also found and fixed a merge accident in 91c2c2b adds Not addressed: the suggestion to turn the "membership check + call NC" pattern into a single generic default method for |
PreImagesElm for field homomorphisms compared IsInjective with 1, a GAP3 leftover: the injective branch was dead, so every nonzero element got the empty preimage, even under bijective maps such as Frobenius automorphisms. With that branch reachable, PreImagesElm needs PreImagesRepresentative, which had no applicable method for Frobenius automorphisms. Add one that delegates to ImagesRepresentative of the inverse; the inverse of a Frobenius automorphism is again one (or the identity), so this cannot recurse. Note for #6409 (renames these operations to NC variants): the fixed comparison then belongs in PreImagesElmNC, and the new method in fieldfin.gi should be installed on PreImagesRepresentativeNC. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
I have completely lost touch with what is going on here, but believe that there is not much more to do? I hope someone else can take this PR over? |
|
@cdwensley sorry for the chaos, and thank you for shepherding this until here. But I think we are almost done! I'll take this over together with @ThomasBreuer to get it over the finish line soon. |
Add PreImagesElmNC, PreImagesRepresentativeNC and PreImagesSetNC alongside the existing operations, and document the division of labour between them: the non-NC versions signal an error if the given object is not in the range of the mapping, return fail (for elements) resp. the preimage of its intersection with the image (for sets) if it is in the range but not in the image, and only then delegate to the NC version, which performs no checks. Previously the operations promised a result for objects outside the image but in fact returned a wrong element or ran into an error. Co-authored-by: Thomas Breuer <sam@math.rwth-aachen.de> Co-authored-by: Max Horn <max@quendi.de> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Move every existing method for PreImagesElm, PreImagesRepresentative and PreImagesSet to the corresponding NC operation, and install new methods for the non-NC operations which perform the range and image checks before delegating. The call sites inside the mapping machinery itself switch to the NC operations along with this, since they legitimately ask for preimages of objects outside the image. The FGA package installs a method for PreImagesRepresentative of a surjective endomorphism of a free group, which the checked version can no longer reach; the regression test for issue T00264 therefore calls the NC variant. Co-authored-by: Thomas Breuer <sam@math.rwth-aachen.de> Co-authored-by: Sam Tertooy <5571903+stertooy@users.noreply.github.com> Co-authored-by: Max Horn <max@quendi.de> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Mechanical change: wherever the library asks for preimages of an object it has already established to lie in the image, call the NC operation, so that the newly added checks are not repeated.
Exercise the three branches of the non-NC operations -- object in the image, in the range but not the image, and outside the range -- for the main kinds of mapping: perm, pc and fp group homomorphisms, general mappings by elements, composition, identity, inverse and zero mappings, mappings by function, action homomorphisms, direct product embeddings and projections, field automorphisms, vector space homomorphisms and binary relations. Co-authored-by: cdwensley <cdwensley.maths@btinternet.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
OK history squashed into four commits. Which I have not yet reviewed myself, but others, feel free to do so now. I'll also do it later. I hope we can merge this soon :-) |
ThomasBreuer
left a comment
There was a problem hiding this comment.
With this distribution into commits, this is indeed easier to review.
One comment addresses a range vs. image question, the others are technical.
| ## <C>PreImagesElm</C> was renamed <C>PreImagesElmNC</C> | ||
| ## throughout the library, and the new <C>PreImagesElm</C> checks that | ||
| ## <A>elm</A> is an element of the image before calling <C>PreImagesElmNC</C>. | ||
| ## If <A>elm</A> is in the range but not in the image then <A>fail</A> |
| ## was renamed <C>PreImagesRepresentativeNC</C> throughout the library, | ||
| ## and the new <C>PreImagesRepresentative</C> checks that <A>elm</A> is an | ||
| ## element of the image before calling <C>PreImagesRepresentativeNC</C>. | ||
| ## If <A>elm</A> is in the range but not in the image then <A>fail</A> |
| ## Anything may happen if <A>elm</A> is not an element of the range of | ||
| ## <A>map</A>. | ||
| ## If <A>elm</A> is not an element of the image of <A>map</A> | ||
| ## then an error message is returned. |
There was a problem hiding this comment.
"an error message is returned" sounds strange
| ## In the third form it delegates to <Ref Oper="PreImagesSet"/>. | ||
| ## <P/> | ||
| ## If the second argument is not an element or a subset of the range of | ||
| ## If the second argument is not an element or a subset of the image of |
There was a problem hiding this comment.
This is true for PreImage( map, elm ), since map must be surjective in this case.
PreImage( map, set ) checks whether set is a subset of Range( map ). If yes then it calls PreImagesSet( map, set ), and this admits set not contained in Image( map ).
| Error( "no default method for s.p. general mapping" ); | ||
| end ); | ||
|
|
||
| InstallMethod( PreImagesRepresentativeNC, |
There was a problem hiding this comment.
This is a duplicate method installation.
| FamRangeEqFamElm, | ||
| [ IsSPGeneralMapping, IsObject ], 0, | ||
| function( map, elm ) | ||
| Error( "no default method for s.p. general mapping" ); |
There was a problem hiding this comment.
Now this is another duplicate.
This aims to continue work on the process outlined in issue #4809, and started in PR #5073.
(The latter PR was so far out of sync with the master that rebasing has proved to be very difficult, hence this version.)
The operations PreImages, PreImagesSet, PreImagesElm and PreImagesRepresentative have all been renamed throughout the library by adding 'NC' to their names. New versions of the four operations have been introduced which just add a simple test and then call the NC versions.
Authors of packages which include a method for one of the four operations have been asked to adjust their packages to prepare for the change. The packages which have merged a PR, and made a release after that are: cryst, fr, orb, polycyclic, matgrp, qpa, rcwa, semigroups, utils and wedderga, while fga has merged a PR but not made a release.
The fining package has closed PR#28 without merging it - it installs another method for PreImagesSet.